package IC.Parser;

 
%%


%class Lexer
%public
%function next_token
%type Token
%line
%scanerror LexicalError
%cup
%state COMMENTS
%state COMMENTS2
%state COMMENTS3
%state QUOTEDSTRING
%{
	StringBuffer s= new StringBuffer();
%}

%eofval{
	if (yystate() == COMMENTS || yystate() == COMMENTS2 || yystate() == COMMENTS3) 
		throw new LexicalError("Lexical error: Comment left open", yyline);
	else if (yystate() == QUOTEDSTRING) 
		throw new LexicalError("Lexical error: String left open", yyline);
	else
  		return new Token(sym.EOF,yyline);
%eofval}


ALPHA=[A-Za-z_] 
DIGIT=[0-9]
ALPHA_NUMERIC={ALPHA}|{DIGIT}
NUMBER=({DIGIT})+	
ILLEGAL_NUMER=[0]({DIGIT})+
ASCII = [\ \!\#-\[\]-\~]

%%

//A rule for // comments
<YYINITIAL> "//" { yybegin(COMMENTS); }
<COMMENTS> . { }
<COMMENTS> [\n] { yybegin(YYINITIAL); }


//A rule for /**/ comments
<YYINITIAL> "/*" { yybegin(COMMENTS2); }
<COMMENTS2> "*" { yybegin(COMMENTS3);} 
<COMMENTS2> [^\*] {  }

<COMMENTS3> "*" {  }
<COMMENTS3>	"/" { yybegin(YYINITIAL); }
<COMMENTS3>	[^\*/] { yybegin (COMMENTS2); }



//A rule for string
<YYINITIAL> \" {s.setLength(0); s.append('\"'); 
				yybegin(QUOTEDSTRING);}


	
	
<QUOTEDSTRING> 	{ASCII} | \\t | \\n | \\\" | \\\\ {s.append(yytext()); }
<QUOTEDSTRING> 	\n|\r|\r\n {throw new LexicalError("Unprintable ASCII character inside string",yyline); }
<QUOTEDSTRING> 	[^\\t\\n\\r\\\"ASCII]|\\ { throw new LexicalError("illegal character  '"+ yytext() +"'", yyline); }
<QUOTEDSTRING> 	\" { yybegin(YYINITIAL);s.append(yytext()); return new Token(sym.QUOTE, yyline, s.toString());}


<YYINITIAL>  [\t|\n|\r|\r\n| ]  {}

<YYINITIAL> "(" 				{return new Token (sym.LP,yyline); }
<YYINITIAL> ")" 				{return new Token (sym.RP,yyline); }
<YYINITIAL> "=" 				{return new Token (sym.ASSIGN,yyline);}
<YYINITIAL> "boolean"			{return new Token (sym.BOOLEAN,yyline); }
<YYINITIAL> "break"				{return new Token (sym.BREAK,yyline);}
<YYINITIAL> "class" 			{return new Token (sym.CLASS,yyline);}
<YYINITIAL> "," 				{return new Token (sym.COMMA,yyline);}
<YYINITIAL> "continue"			{return new Token (sym.CONTINUE,yyline);}
<YYINITIAL> "/"					{return new Token (sym.DIVIDE,yyline);}
<YYINITIAL> "."					{return new Token (sym.DOT,yyline);}
<YYINITIAL> "=="				{return new Token (sym.EQUAL,yyline);}
<YYINITIAL> "extends"			{return new Token (sym.EXTENDS,yyline);}
<YYINITIAL> "else"				{return new Token (sym.ELSE,yyline);}
<YYINITIAL> "false"				{return new Token (sym.FALSE,yyline);}
<YYINITIAL> ">"					{return new Token (sym.GT,yyline);}
<YYINITIAL> ">="				{return new Token (sym.GTE,yyline);}
<YYINITIAL> "if"				{return new Token (sym.IF,yyline);}
<YYINITIAL> "int"				{return new Token (sym.INT,yyline);}
<YYINITIAL> "&&"				{return new Token (sym.LAND,yyline);}
<YYINITIAL> "["					{return new Token (sym.LB,yyline);}
<YYINITIAL> "{"					{return new Token (sym.LCBR,yyline);}
<YYINITIAL> "length"			{return new Token (sym.LENGTH,yyline);}
<YYINITIAL> "new"				{return new Token (sym.NEW,yyline);}
<YYINITIAL> "!"					{return new Token (sym.LNEG,yyline);}
<YYINITIAL> "||"				{return new Token (sym.LOR,yyline);}
<YYINITIAL> "<"					{return new Token (sym.LT,yyline);}
<YYINITIAL> "<="				{return new Token (sym.LTE,yyline);}
<YYINITIAL> "-"					{return new Token (sym.MINUS,yyline);}
<YYINITIAL> "%"					{return new Token (sym.MOD,yyline);}
<YYINITIAL> "*"					{return new Token (sym.MULTIPLY,yyline);}
<YYINITIAL> "!="				{return new Token (sym.NEQUAL,yyline);}
<YYINITIAL> "null"				{return new Token (sym.NULL,yyline);}
<YYINITIAL> "+"					{return new Token (sym.PLUS,yyline);}
<YYINITIAL> "]"					{return new Token (sym.RB,yyline);}
<YYINITIAL> "}"					{return new Token (sym.RCBR,yyline);}
<YYINITIAL> "return"			{return new Token (sym.RETURN,yyline);}
<YYINITIAL> ";"					{return new Token (sym.SEMI,yyline);}
<YYINITIAL> "static"			{return new Token (sym.STATIC,yyline);}
<YYINITIAL> "string"			{return new Token (sym.STRING,yyline);}
<YYINITIAL> "this"				{return new Token (sym.THIS,yyline);}
<YYINITIAL> "true"				{return new Token (sym.TRUE,yyline);}
<YYINITIAL> "void"				{return new Token (sym.VOID,yyline);}
<YYINITIAL> "while"				{return new Token (sym.WHILE,yyline);}

<YYINITIAL> [A-Z]({ALPHA_NUMERIC})*				{return new Token (sym.CLASS_ID,yyline,yytext());}
<YYINITIAL> [a-z]({ALPHA_NUMERIC})* 				{return new Token (sym.ID,yyline,yytext());}
<YYINITIAL> {ILLEGAL_NUMER}         {throw new LexicalError("Illegal Number: starts with 0", yyline);}
<YYINITIAL> {NUMBER}	{
	try {
		Integer.parseInt(yytext());
		return new Token (sym.INTEGER,yyline,Integer.parseInt(yytext()));
    }
	catch (NumberFormatException e) {
		throw new LexicalError( "Integer out of range",yyline);
	}
       
	}
<YYINITIAL>  [0-9]+({ALPHA})+		{ throw new LexicalError("Bad identifier: " + yytext(), yyline); }


 
 

.|\n {throw new LexicalError( "Invalid token",yyline);}
      





